package tool;

import gui.ButtonColors;
import gui.RoundedBorder;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;

/** Un CustomizedButton è principalmente un JButton, i cui angoli
 *  possono essere resi arrotondati. Inoltre, è possibile personalizzare
 *  il colore del riempimento, del bordo e del testo.
 * @author Daniele
 * @version 2.4 */
public class CustomizedButton extends JButton implements MouseListener {
	
	//TODO per gestire lo stato del jbutton potrebbe essere più utile e svelto usare ButtonModel (this.model)con le sue funzioni ispressed eccetera!!!
	
	private static final long serialVersionUID = 6479645275513122308L;
	
	/** Rappresenta lo stato del pulsante quando il puntatore non interagisce con esso. */
	public static final int BUTTON_DEFAULT = 0;
	/** Rappresenta lo stato del pulsante quando il puntatore si trova sopra di esso. */
	public static final int BUTTON_OVER = 1;
	/** Rappresenta lo stato del pulsante quando il puntatore è premuto sopra di esso. */
	public static final int BUTTON_PRESSED = 2;
	/** Rappresenta lo stato del pulsante quando è inattivo. */
	public static final int BUTTON_INACTIVE = 3;
	
	/** lunghezza del diametro della circonferenza che verrà utilizzata per disegnare gli angoli arrotondati. */
	private int arcDiameter;
	/** set di colori usato per riempire il pulsante. */
	private ButtonColors fillColour;
	/** set di colori usato per tingere il contorno del pulsante. */
	private ButtonColors edgeColour;
	/** spessore della linea utilizzata per tracciare il contorno del pulsante. */
	private int thickness;
	/** il tipo di font utilizzato per comporre la scritta sul pulsante. */
	private String font_name;
	/** set di colori usato per disegnare i caratteri della stringa. */
	private ButtonColors fontColour;
	/** valore intero che rappresenta lo stato del pulsante per interazione col puntatore. */
	private int state;
	
	
	/** Costruisce un pulsante dalle caratteristiche personalizzabili.
	 *  Se ne possono arrotondare gli angoli e impostare le colorazioni
	 *  dell'interno, del contorno e del testo.
	 * @param _name				stringa trascritta sul pulsante.
	 * @param _arcDiameter		lunghezza del diametro della circonferenza usata per disegnare gli angoli arrotondati.
	 * @param _fill_colour		colore usato per riempire l'interno del pulsante.
	 * @param _over_fill_colour colore usato per riempire l'interno del pulsante, quando il puntatore ci è sopra.
	 * @param _edge_colour		colore usato per tingere il contorno del pulsante.
	 * @param _over_edge_colour colore usato per tingere il contorno del pulsante, quando il puntatore ci è sopra.
	 * @param _line_thickness	spessore della linea utilizzata per tracciare il contorno del pulsante.
	 * @param _font_name		il tipo di font utilizzato per comporre la scritta sul pulsante.
	 * @param _font_colour		colore usato per disegnare i caratteri della stringa.
	 * @param _over_font_colour colore usato per disegnare i caratteri della stringa quando il puntatore è sopra il tasto. */
	public CustomizedButton(String _name, int _arcDiameter,
							Color _fill_colour, Color _over_fill_colour, Color _pressed_fill_colour,
							Color _edge_colour, Color _over_edge_colour, Color _pressed_edge_colour, int _line_thickness, String _font_name,
							Color _font_colour, Color _over_font_colour, Color _pressed_font_colour){
		super(_name);
		this.setOpaque(false);
		arcDiameter = _arcDiameter;
		fillColour = new ButtonColors(_fill_colour,_over_fill_colour,_pressed_fill_colour,Color.WHITE);
		edgeColour = new ButtonColors(_edge_colour,_over_edge_colour,_pressed_edge_colour,Color.DARK_GRAY);
		fontColour = new ButtonColors(_font_colour,_over_font_colour,_pressed_font_colour,Color.DARK_GRAY);
		thickness = _line_thickness;
		font_name = _font_name;
		this.addMouseListener(this);
	}
	
	public void paint(Graphics g){
		
		Dimension size = this.getSize();
		Font font = new Font(font_name, Font.PLAIN, (size.height)/3);

		g.setFont(font);
		FontMetrics metrics = g.getFontMetrics(font);
		
		RoundedBorder border = new RoundedBorder(edgeColour.buttonColours[state], fillColour.buttonColours[state], this.thickness, this.arcDiameter);
		border.paintBorder(this, g, 0, 0, size.width, size.height);
		
		g.setColor(fontColour.buttonColours[state]);
		g.drawString(
				this.getText(),
				(int) (size.width-(metrics.getStringBounds(this.getText(), g)).getWidth())/2,
				(int) (size.height+(metrics.getStringBounds(this.getText(), g)).getHeight())/2
					);
	}
	
	/** Metodo overridden che imposta lo stato attivo
	 *  oppure disattivo del pulsante. */
	@Override
	public void setEnabled(boolean flag){
		super.setEnabled(flag);
		this.state = (flag ? BUTTON_DEFAULT : BUTTON_INACTIVE);
		this.repaint();
	}

	/** Metodo che disattiva un pulsante, cambiandone l'aspetto
	 *  e rimuovendo il listener in ascolto. */
	@Deprecated
	public void deactivate(){
		this.state = BUTTON_INACTIVE;
		this.removeMouseListener(this);
		this.repaint();
	}
	
	/** Metodo che attiva un pulsante, cambiandone l'aspetto e
	 *  registrando il listener, consentendogli l'ascolto. */
	@Deprecated
	public void activate(){
		this.state = BUTTON_DEFAULT;
		this.addMouseListener(this);
		this.repaint();
	}
	
	@Override
	public void mouseClicked(MouseEvent arg0) {
		// avendo già specificato gli stati Pressed e Realeased,
		// non è necessario specificare quest'altra possibilità.
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		if(this.isEnabled()) {this.state = BUTTON_OVER;}
		this.repaint();
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		if(this.isEnabled()) {this.state = BUTTON_DEFAULT;}
		this.repaint();
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		if(this.isEnabled()) {this.state = BUTTON_PRESSED;}
		this.repaint();
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		if(this.isEnabled()) {this.state = BUTTON_OVER;}
		this.repaint();
	}
}
